package com.zhuyuan.auth.granter;

import com.alibaba.fastjson2.JSON;
import com.zhuyuan.core.constant.Oauth2Constants;
import com.zhuyuan.core.enums.ResultCodeEnum;
import com.zhuyuan.core.exception.AuthException;
import com.zhuyuan.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @description: 账号-密码-验证码 登录模式
 * grantType: captcha
 * @param: captchaKey;(Oauth2Constants.CAPTCHA_HEADER_KEY),验证码key,在生成验证码时生成uuid回传客户端,来获取redis中的验证码
 * @param: captchaCode;(Oauth2Constants.CAPTCHA_HEADER_CODE),验证码
 * @param: username;(Oauth2Constants.USERNAME),验证码
 * @param: password;(Oauth2Constants.PASSWORD),密码
 * @author: 张琳凯
 * @date: 2025/1/20 10:40
 **/
@Slf4j
public class CaptchaTokenGranter extends AbstractTokenGranter {

	private final AuthenticationManager authenticationManager;

	private RedisService redisService;

	public CaptchaTokenGranter(AuthenticationManager authenticationManager,
	                           AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService,
	                           OAuth2RequestFactory requestFactory, RedisService redisService) {
		this(authenticationManager, tokenServices, clientDetailsService, requestFactory, Oauth2Constants.CAPTCHA_GRANT_TYPE);
		this.redisService = redisService;
	}

	protected CaptchaTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices,
	                              ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
		super(tokenServices, clientDetailsService, requestFactory, grantType);
		this.authenticationManager = authenticationManager;
	}

	@Override
	protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {

        Map<String, String> requestParameters = tokenRequest.getRequestParameters();
		// 增加验证码判断
		String key = requestParameters.get(Oauth2Constants.CAPTCHA_HEADER_KEY);
		String code = requestParameters.get(Oauth2Constants.CAPTCHA_HEADER_CODE);
        if (StringUtils.isAnyEmpty(key,code)) {
            throw new OAuth2Exception("请求参数不存在！");
        }
        Object codeFromRedis = redisService.getCacheObject(Oauth2Constants.REDIS_CAPTCHA_KEY + key);
		codeFromRedis="123";
		if (StringUtils.isBlank(code)) {
			throw new UserDeniedAuthorizationException("请输入验证码");
		}
		if (codeFromRedis == null) {
			throw new UserDeniedAuthorizationException("验证码已过期");
		}
		if (!StringUtils.equalsIgnoreCase(code, codeFromRedis.toString())) {
			throw new UserDeniedAuthorizationException("验证码不正确");
		}

		redisService.deleteObject(Oauth2Constants.REDIS_CAPTCHA_KEY + key);

		Map<String, String> parameters = new LinkedHashMap<String, String>(requestParameters);
		String username = parameters.get(Oauth2Constants.USERNAME);
		String password = parameters.get(Oauth2Constants.PASSWORD);
		// Protect from downstream leaks of password
		parameters.remove("password");

		Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
		((AbstractAuthenticationToken) userAuth).setDetails(parameters);
		try {
            // 使用 AuthenticationManager 进行认证
			userAuth = authenticationManager.authenticate(userAuth);
		} catch (AccountStatusException | BadCredentialsException ase) {

			log.error("登录失败:", ase);
			String errorMsg = ase.getMessage();
			if (errorMsg.contains("Bad credentials")) {
				throw new AuthException(ResultCodeEnum.INVALID_USERNAME_PASSWORD);
			} else if (errorMsg.contains("User is disabled")) {
				throw new AuthException(ResultCodeEnum.DISABLED_ACCOUNT);
			}else {
				throw new AuthException(ResultCodeEnum.INVALID_CAPTCHA);
			}
		}

		if (userAuth == null || !userAuth.isAuthenticated()) {
			throw new InvalidGrantException("Could not authenticate user: " + username);
		}
//		SecurityContextHolder.getContext().setAuthentication(userAuth);
		OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
		return new OAuth2Authentication(storedOAuth2Request, userAuth);
	}

}
